package build_dao

import (
	"fmt"
	"go_server/game_server/database/mysql"
	"go_server/zinx/zlog"
	"go_server/zinx/zutils"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
)

type Build struct {
	Id string `gorm:"column:Id;primary"`
	RoleId int64 `gorm:"column:role_id"`
	MapId int32 `gorm:"column:map_id"`
	ConfigKey int32 `gorm:"column:config_key"`
	ConfigId int32 `gorm:"column:config_id"`
	BuildServerId int32 `gorm:"column:build_server_id"`
	BlockId int32 `gorm:"column:block_id"`
	BuildLevel int32 `gorm:"column:build_level"`
	BuildPosX int32`gorm:"column:build_posX"`
	BuildPosZ int32`gorm:"column:build_posZ"`
	ConsumeStatus int32`gorm:"column:consume_status"`
	ClickType int32`gorm:"column:click_type"`
}

const (
	bUILD_CONFIG_INDEX = iota
	bUILD_SERVER_INDEX
	bUILD_LEVEL_INDEX
	bUILD_POSX_INDEX
	bUILD_POSZ_INDEX
	bUILD_CFGKEY_INDEX
	bUILD_CONSUME_INDEX
	bUILD_CLICK_TYPE
)



func (Build) TableName() string {
	return "build_info"
}

var(
	all_build_field = zutils.GetGormFields(Build{})
)

func GetBuildByKey(key string) *Build {
	db := mysql.GetServerDBConnection()
	var build Build
	if err := db.Select(all_build_field).Where("Id=?", key).First(&build).Error; err != nil {
		if err != gorm.ErrRecordNotFound {
			zlog.Errorf("GetBuildByKey ERR!!! Id: %s, err: %v", key, err)
		}
		return nil
	}
	return &build
}

func GetBuildByMapId(roleId int64, mapId int32) []*Build {
	db := mysql.GetServerDBConnection()
	var builds []*Build
	if err := db.Select(all_build_field).Where(&Build{RoleId: roleId, MapId: mapId}).
		Find(&builds).Error; err != nil {
		if err != gorm.ErrRecordNotFound {
			zlog.Errorf("GetBuildByMapId ERR!!! roleId: %d, mapId: %d, err: %v", roleId, mapId, err)
		}
		return nil
	}
	return builds
}

func UpdateBuildByKey(key string, changeField *map[string]any) {
	db := mysql.GetServerDBConnection()
	if err := db.Model(Build{}).Where("Id=?", key).Updates(changeField).Error; err != nil {
		zlog.Errorf("UpdateBuildByKey %s data failed: %v", key, err)
	}
}

func NewOrUpdateBuildData(mapId int32, datamap map[uint8][][]int32, roleId int64) {
	buildArr := make([]*Build, 0)
	for areaId, build := range datamap {
		for _, posInfo := range build {
			buildObj := &Build{
				RoleId:       roleId,
				MapId:        mapId,
				BlockId: int32(areaId),
				ConfigId: posInfo[bUILD_CONFIG_INDEX],
				BuildServerId: posInfo[bUILD_SERVER_INDEX],
				BuildLevel: posInfo[bUILD_LEVEL_INDEX],
				BuildPosX: posInfo[bUILD_POSX_INDEX],
				BuildPosZ: posInfo[bUILD_POSZ_INDEX],
				ConfigKey: posInfo[bUILD_CFGKEY_INDEX],
				ConsumeStatus: posInfo[bUILD_CONSUME_INDEX],
				ClickType: posInfo[bUILD_CLICK_TYPE],
				Id:   fmt.Sprintf("%d-%d-%d-%d", roleId, mapId, posInfo[bUILD_CONFIG_INDEX],
					posInfo[bUILD_SERVER_INDEX]),
			}
			buildArr = append(buildArr, buildObj)
		}
	}

	db := mysql.GetServerDBConnection()
	if err := db.Clauses(clause.OnConflict{
		Columns: []clause.Column{{Name: "id"}},
		DoUpdates: clause.AssignmentColumns([]string{"block_id", "config_key", "build_level", "build_posX",
			"build_posZ", "consume_status", "click_type"}),
	}).Create(buildArr).Error; err != nil {
		zlog.Errorf("create or update Build %v data failed: %v", buildArr, err)
	}
}